﻿//========================================================= 
/**@file TimedCommand.h
 * @brief 带超时功能的命令(用于CommandAsyncWorker处理回调)
 * 
 * @date 2017-08-09   14:36:45
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_TIMEDCOMMAND_H_
#define _LIBZHOUYB_TIMEDCOMMAND_H_
//--------------------------------------------------------- 
#include "../CommandDriver.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
namespace async {
//--------------------------------------------------------- 
/**
 * @brief 带超时功能的命令(用于CommandTaskExcutor回调,如:等待放卡10s)
 * @date 2017-08-09 22:12
 */
class TimedCommand : public ICommandHandler, public RefObject
{
protected:
    Timer _timer;
    uint _timeoutMs;
    bool _isCancel;
    Ref<ICommandHandler> _callback;

    /// 返回任务是否需要继续作为后台任务运行
    DeviceError::ErrorCode TimedTask(Arguments& arg, Arguments& rlt)
    {
        if(CommandTaskExecutor::IsTaskOK(arg))
            return DeviceError::Success;
        if(_isCancel)
            return DeviceError::OperatorInterruptErr;
        if(_timer.Elapsed() >= _timeoutMs)
            return DeviceError::WaitTimeOutErr;
        return DeviceError::DevIsBusyErr;
    }
public:
    static Ref<TimedCommand> Timed(Ref<ICommandHandler> callback, uint timeoutMs)
    {
        Ref<TimedCommand> timedCallback = Command::Make<TimedCommand>();
        return timedCallback->Start(callback, timeoutMs);
    }
public:
    TimedCommand() {}
    virtual ~TimedCommand() { Cancel(); }
    virtual bool OnCommand(Arguments& arg, Arguments& rlt)
    {
        DeviceError::ErrorCode errCode = TimedTask(arg, rlt);
        if(errCode == DeviceError::DevIsBusyErr)
            return false;
        CommandTaskExecutor::SetIsBackground(arg, false);
        if(!_callback.IsNull())
        {
            arg.Put("Task::CODE", ArgConvert::ToString(errCode));
            _callback->OnCommand(arg, rlt);
        }
        return true;
    }
    virtual bool IsRunable() const { return true; }
    inline TimedCommand& Start(Ref<ICommandHandler> callback, uint timeoutMs)
    {
        _callback = callback;
        return Start(timeoutMs);
    }
    TimedCommand& Start(uint timeoutMs)
    {
        _timeoutMs = timeoutMs;
        _isCancel = false;
        _timer.Restart();
        return (*this);
    }
    inline void SetWaitTimeout(uint timeoutMs)
    {
        _timeoutMs = timeoutMs;
    }
    inline void Cancel()
    {
        _isCancel = true;
    }
};
//--------------------------------------------------------- 
} // namespace async
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_TIMEDCOMMAND_H_
//========================================================= 